package com.cenxi.manage;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cenxi.common.constants.Constants;
import com.cenxi.common.convert.RoleDTOTORoleEntity;
import com.cenxi.common.dto.req.RoleReqDTO;
import com.cenxi.common.dto.resp.MenuRespDTO;
import com.cenxi.common.dto.resp.RoleRespDTO;
import com.cenxi.common.exceptions.ServiceException;
import com.cenxi.common.util.MenuUtils;
import com.cenxi.common.util.req.PageReq;
import com.cenxi.common.util.req.Req;
import com.cenxi.common.util.resp.PageResp;
import com.cenxi.common.util.resp.Resp;
import com.cenxi.dao.domain.Menu;
import com.cenxi.dao.domain.Role;
import com.cenxi.dao.domain.RoleMenu;
import com.cenxi.dao.mapper.MenuMapper;
import com.cenxi.dao.mapper.RoleMapper;
import com.cenxi.dao.mapper.RoleMenuMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author cenxi
 * @Date 2023/8/16 11:47
 * @Version 1.0
 */
@Slf4j
@Component
public class ManageRoleService {

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RoleMenuMapper roleMenuMapper;
    @Autowired
    private MenuMapper menuMapper;
    public Resp<List<RoleRespDTO>> list(Req<Void> req) {
        return Resp.succeed(roleMapper.selectList(new LambdaQueryWrapper<Role>()
                        .eq(Role::getDeleted, Constants.ENABLE)
                        .eq(Role::getState, Constants.ENABLE)).stream()
                .map(RoleDTOTORoleEntity.INSTANCE::entity2dto).collect(Collectors.toList()));
    }

    public PageResp<RoleRespDTO> page(PageReq<RoleReqDTO> req) {
        RoleReqDTO data = req.getData();
        if (Objects.isNull(data)) {
            return PageResp.error("参数错误");
        }
        LambdaQueryWrapper<Role> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Role::getDeleted, Constants.ENABLE)
                .eq(Objects.nonNull(data.getState()), Role::getState, data.getState())
                .eq(Objects.nonNull(data.getRoleId()), Role::getRoleId, data.getRoleId());
        Page<Role> rolePage = roleMapper.selectPage(new Page<>(req.getPageIndex(), req.getPageSize()), lqw);
        List<RoleRespDTO> roleRespDTOS = RoleDTOTORoleEntity.INSTANCE.entity2dto(rolePage.getRecords());
        if (!CollectionUtils.isEmpty(roleRespDTOS)) {
            roleRespDTOS.forEach(item -> {
                List<Long> collect = roleMenuMapper.selectList(new LambdaQueryWrapper<RoleMenu>()
                                .eq(RoleMenu::getRoleId, item.getRoleId())).stream().map(RoleMenu::getMenuId)
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(collect)) {
                    item.setMenus(MenuUtils.treeMenu(menuMapper.selectList(new LambdaQueryWrapper<Menu>()
                            .eq(Menu::getDeleted, Constants.ENABLE)
                            .eq(Menu::getState, Constants.ENABLE)
                            .in(Menu::getId, collect))));
                }
            });
        }
        return PageResp.succeed(rolePage.getPages(), rolePage.getTotal(),
                rolePage.hasNext(), roleRespDTOS);
    }

    @Transactional(rollbackFor = Exception.class)
    public Resp<Boolean> create(Req<RoleReqDTO> req) {
        RoleReqDTO data = req.getData();
        if (Objects.isNull(data)) {
            return Resp.error("参数错误");
        }
        Role role = RoleDTOTORoleEntity.INSTANCE.roleReqTORole(data);
        // 检查是否存在相同角色
        LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Role::getRoleName, role.getRoleName());
        if (roleMapper.exists(wrapper)) {
            return Resp.error("角色参数错误");
        }
        if (roleMapper.insert(role) > 0) {
            if (!CollectionUtils.isEmpty(data.getMenus())) {
                for (MenuRespDTO menu : data.getMenus()) {
                    if (Objects.nonNull(menuMapper.selectById(menu.getId()))) {
                        RoleMenu roleMenu = new RoleMenu();
                        roleMenu.setRoleId(role.getRoleId());
                        roleMenu.setMenuId(Long.valueOf(menu.getId()));
                        roleMenuMapper.insert(roleMenu);
                    }
                }
            }
            return Resp.succeed(true);
        }
        return Resp.error(false);
    }

    @Transactional(rollbackFor = Exception.class)
    public Resp<Boolean> edit(Req<RoleReqDTO> req) {
        RoleReqDTO data = req.getData();
        if (Objects.isNull(data)) {
            return Resp.error("参数错误");
        }
        // 按需修改
        Role role = new Role();
        role.setRoleName(data.getRoleName());
        role.setState(data.getState());
        role.setRemark(data.getRemark());
        LambdaQueryWrapper<Role> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Role::getRoleId, data.getRoleId());
        if (roleMapper.update(role, lqw) > 0) {
            if (!CollectionUtils.isEmpty(data.getMenus())) {
                // 修改角色绑定路由/先删后加
                roleMenuMapper.delete(new LambdaQueryWrapper<RoleMenu>()
                        .eq(RoleMenu::getRoleId, data.getRoleId()));
                for (MenuRespDTO menu : data.getMenus()) {
                    // 查看角色是否存在
                    if (Objects.nonNull(roleMenuMapper.selectById(menu.getId()))) {
                        RoleMenu roleMenu = new RoleMenu();
                        roleMenu.setRoleId(Long.valueOf(data.getRoleId()));
                        roleMenu.setMenuId(Long.valueOf(menu.getId()));
                        roleMenuMapper.insert(roleMenu);
                    }
                }
            }
            return Resp.succeed(true);
        }
        return Resp.succeed(false);
    }

    public Resp<RoleRespDTO> findById(Req<String> req) {
        if (Objects.isNull(req.getData())) {
            return Resp.error("参数错误");
        }
        Role role = roleMapper.selectById(req.getData());
        if (Objects.isNull(role)) {
            return Resp.error("没有该角色: " + req.getData());
        }
        RoleRespDTO roleRespDTO = RoleDTOTORoleEntity.INSTANCE.entity2dto(role);
        List<Long> collect = roleMenuMapper.selectList(new LambdaQueryWrapper<RoleMenu>()
                .eq(RoleMenu::getRoleId, req.getData()))
                .stream().map(RoleMenu::getMenuId)
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(collect)) {
            List<Menu> menus = menuMapper.selectBatchIds(collect);
            roleRespDTO.setMenus(MenuUtils.treeMenu(menus));
        }
        return Resp.succeed(roleRespDTO);
    }

    public Resp<Boolean> enable(String data, byte enable) {
        Role role = roleMapper.selectById(data);
        if (Objects.isNull(role)) {
            return Resp.error("没有该角色: " + data);
        }
        Role rl = new Role();
        rl.setRoleId(role.getRoleId());
        rl.setState((int) enable);
        return Resp.succeed(roleMapper.updateById(rl) > 0);
    }

    public Resp<Boolean> disable(String data, byte disable) {
        Role role = roleMapper.selectById(data);
        if (Objects.isNull(role)) {
            return Resp.error("没有该角色: " + data);
        }
        Role rl = new Role();
        rl.setRoleId(role.getRoleId());
        rl.setState((int) disable);
        return Resp.succeed(roleMapper.updateById(rl) > 0);
    }

    public Resp<Boolean> deleteById(String data) {
        if (roleMapper.deleteById(data) > 0) {
            // 删除角色绑定路由
            LambdaQueryWrapper<RoleMenu> lqw = new LambdaQueryWrapper<>();
            lqw.eq(RoleMenu::getRoleId, data);
            roleMenuMapper.delete(lqw);
            return Resp.succeed(true);
        }
        return Resp.succeed(false);
    }
}
